home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 11 / Cream of the Crop 11-2.iso / extra / backgmmn.zip / BACKEVAL.C < prev    next >
C/C++ Source or Header  |  1995-12-27  |  10KB  |  395 lines

  1. /********************************************************************/
  2. /*                                                                  */
  3. /*  Hoser BackGammon version 1.0                                    */
  4. /*                                                                  */
  5. /*      Robert Pfister                                              */
  6. /*  Copyright  June,1987 all rights reserved.                       */
  7. /********************************************************************/
  8.  
  9. /****************************************************************/
  10. /* These routines  do all the thinking for the computer side    */
  11. /* (read: the magic lives here)                                 */
  12. /****************************************************************/
  13.  
  14. /* This file contains:
  15.     Eval        vulnerable    doom        [CopyBoard]
  16.     DoMove        FindMove    GenerateMoves    Find4
  17.     Find3        Find2        Find1
  18. */
  19. #include "back.h"
  20. #include <string.h>
  21.  
  22. #define Running  1
  23. #define Blocking 2
  24. #define Pegging  3
  25. #define BackGame 4
  26.  
  27. extern you_me_rec    me;
  28.  
  29. int    Moves  = 0,    AvgPos = 0,
  30.     LastVun = 0,    list[4][2],
  31.     count = 0,    max = 0,
  32.     GameStat = 0,    MaxStat = 0;
  33. const BYTE
  34.     block[26] = {-1,1,2,3,4,5,6,  8,9,10,11,12,13   ,14,15,17,21,25,27,
  35.                  25,21,19,8,3,1,0},
  36.     run[26]   = {-1,1,2,3,4,5,6,  15,16,17,18,19,20,  30,31,32,33,34,35,
  37.                50,51,52,53,54,55},
  38.     peg[26]   = {-20,0,0,0,0,0,0 ,1,2,3,4,5,6, 30,31,32,33,34,35,
  39.                 50,49,48,47,46,45,0},
  40.     back[26] = {20,40,30,20,10,5,0 ,1,2,3,4,5,6, 30,31,32,30,40,50,
  41.                 50,49,48,30,20,10,0};
  42.  
  43. int doom(BYTE Board[26])
  44. {
  45.   int    i, value = 0;
  46.  
  47.   if (LastVun == 0)
  48.     return(0);
  49.   /* find the "doom" factor..the possibility of getting outa being captured */
  50.   for(i = 1;i <= 10; i++)
  51.     if (Board[i] < -1)
  52.       value += 5;
  53.   return(value);
  54. }
  55.  
  56. int vulnerable(BYTE Board[26], int pos)
  57. {
  58.   int    i,j,k;
  59.   int    value = 0;
  60.   int    HitTable[7][7];
  61.  
  62.   if ( (Board[pos]<0) || (pos == 0) || (Board[pos] >= 2) )
  63.     return 0;
  64.   memset(&HitTable,0,sizeof HitTable);        /*  intitialize table */
  65.  
  66.   for(i = 1; i <= 12; i++)    /* look at all dice within 12 places    */
  67.     if (pos-i >= 0)        /* within the board            */
  68.       if (Board[pos-i] < 0)    /* there exists a piece at that place    */
  69.     if (valid(Board,pos,pos-i,i)) {    /* can capture legally        */
  70.       if (i <= 6)        /* find hits for one die        */
  71.         for(j = 1; j <= 6; j++) {
  72.           HitTable[i][j] = 1;
  73.           HitTable[j][i] = 1;
  74.         }
  75.       for (j = 1;j < i; j++) { /* figure out combinations        */
  76.         k = i-j;        /* first die is j, second is k        */
  77.                 /* check legality of the intermediate place*/
  78.         if (valid (Board,pos,pos-j,j)) {
  79.           HitTable[k][j] = 1;
  80.           HitTable[j][k] = 1;
  81.         }
  82.         if (valid (Board,pos,pos-k,k)) {
  83.           HitTable[k][j] = 1;
  84.           HitTable[j][k] = 1;
  85.         }
  86.       }
  87.     }    /* end if valid (board,position) */
  88.   for(i = 1;i <= 6; i++)    /* find how many hits in that table    */
  89.     for(j = 1;j <= 6; j++)
  90.       if (HitTable[i][j] == 1)
  91.     value++;
  92.   LastVun = value;
  93.   return(value);
  94. }  /* end of vulnerable */
  95.  
  96. int Eval(BYTE Board[26])
  97. {
  98.   int    i;
  99.   int    num = 0, value = 0, me,you;
  100.   int    Msum = 0, Ysum = 0;
  101.  
  102.   /* see who is ahead */
  103.   for(i = 0; i <=24; i++)
  104.     if (Board[i] > 0)
  105.       Msum += (25 - i) * Board[i];
  106.   for(i = 1; i <= 25; i++)
  107.     if (Board[i] < 0)
  108.       Ysum -= i * Board[i];
  109.   for (i = 0; (i <= 24) && (Board[i] <= 0); i++); /* first occurence of me    */
  110.     me = i;
  111.   for (i = 25; (i >= 1) && (Board[i] >= 0); i--); /* first occurence of you    */
  112.     you = i;
  113.          GameStat = BackGame;/* default case                */
  114.   if (Ysum > Msum+10) GameStat = Running;/* if closer to winning than them    */
  115.   if (you > 18)    GameStat = Blocking;/* if an opponent is within the bounds    */
  116.   if (me > you)    GameStat = Pegging;    /* if complete separation        */
  117.   for(i = 0; i <= 24; i++) {
  118.     if (Board[i] > 0) {
  119.       num += Board[i];
  120.       switch(GameStat) {
  121.     case BackGame:
  122.       value += back[i] * Board[i];
  123.       if (i < 18)
  124.         value += 3 * vulnerable(Board,i);
  125.       break;
  126.     case Pegging:
  127.       value += peg[i] * Board[i];
  128.       break;
  129.     case Blocking:
  130.       value += block[i] * Board[i];
  131.       value -= 4 * vulnerable(Board,i);
  132.       value -= 6 * doom(Board);
  133.       break;
  134.     case Running:
  135.       value += run[i] * Board[i];
  136.       value -= 6 * vulnerable(Board,i);
  137.       value -= 6 * doom(Board);
  138.       break;
  139.     }    /* end cases    */
  140.       }        /* end if    */
  141.     }        /* end for    */
  142.  
  143.     /* add points for taking men off...more if no chance of being taken */
  144.     if (GameStat == Pegging)
  145.       value += (15-num) * 300;
  146.     else
  147.       value += (15-num) * 75;
  148.     switch(GameStat) {
  149.       case BackGame:
  150.     num = 0;
  151.     for(i = 0; i <= 6; i++)
  152.       if ((Board[i] > 0) && (you > i))
  153.         num++;
  154.     value += 100 * num;
  155.     num = 0;
  156.     for(i = 15; i <= 21; i++)
  157.       if (Board[i] > 0)
  158.         num += Board[i];
  159.     value += 30 * num;
  160.     value -= 100 * Board[25];
  161.     num = 0;
  162.     for(i = 17; i <= 23; i++)
  163.       if (Board[i] >= 2)
  164.         num++;
  165.     value += (num * 300);
  166.     break;
  167.       /* if blocking game, check the block length...add points for more */
  168.       case Blocking:
  169.     num = 0;
  170.     for(i = 14; i <= 22; i++) {
  171.       if (Board[i] >= 2)
  172.         num++;
  173.       if ((you > i) && (Board[i] >= 2))
  174.         num++;
  175.     }
  176.     value += (num * 400);
  177.     num = 0;
  178.     for(i = 0; i <= 17; i++)
  179.       if (Board[i] > 0)
  180.          num += (Board[i] * (18-i) * (18-i));
  181.     value -= num * 2/3;
  182.     break;
  183.       case Pegging:
  184.       case Running:
  185.     num = 0;
  186.     for(i = 0; i <= 17; i++)
  187.       if (Board[i] > 0)
  188.         num++;
  189.     value -= 10 * num;
  190.     num = 0;
  191.     for(i = 0; i <= 17; i++)
  192.       if (Board[i] > 0)
  193.         num += (Board[i] * (26-i) * (26-i));
  194.     value -= num;
  195.     break;
  196.     }
  197.   return(value);
  198. }
  199.  
  200. /* copy board 1 to board 2 */
  201. #define CopyBoard(b1, b2)    memcpy(b2,b1,sizeof_board)
  202.  
  203. void DoMove(BYTE Board[26], BYTE Dice[4])
  204. {
  205.   int    j;
  206.  
  207.   AvgPos += count;
  208.   /* don't do anything if nothing to be done  */
  209.   if (count == 0) {
  210.     DoMenuStrip("Can't move from this position!!");
  211.     me.wasted += Dice[0] + Dice[1] + Dice[2] + Dice[3];
  212.   }
  213.   else {
  214.     PutMoveNumber(count);
  215.     /* show move */
  216.     for(j = 0; j <= 3; j++)
  217.       if (list[j][0] != -1) {
  218.     BlinkPiece(Board,list[j][0]);
  219.     update(Board,list[j][0],      list[j][1] ,1);
  220.     PutSpike(    list[j][0],Board[list[j][0]]  );
  221.     if ((list[j][1] > 0) && (list[j][1] < 25))    /******/
  222.       BlinkPiece(Board,list[j][1]);
  223.     if (list[j][0] == 0)
  224.       me.wasted += list[j][1];
  225.       }
  226.       else
  227.     me.wasted += Dice[j];
  228.     /* touch up the bars */
  229.     PutSpike(0 ,Board[ 0]);
  230.     PutSpike(25,Board[25]);
  231.   }
  232. }
  233.  
  234. void FindMove(BYTE Board[26],BYTE Dice[4], int i1, int i2, int i3,int i4)
  235. {
  236.   int j;
  237.  
  238.   if ((count<50)||(10 *(count/10) == count))
  239.     PutMoveNumber(count);
  240.   j = Eval(Board);
  241.   if ((count == 1) || (j > max)) {
  242.     max = j;
  243.     MaxStat = GameStat;
  244.     list[0][0] = i1; list[0][1] = i1 + Dice[0];
  245.     list[1][0] = i2; list[1][1] = i2 + Dice[1];
  246.     list[2][0] = i3; list[2][1] = i3 + Dice[2];
  247.     list[3][0] = i4; list[3][1] = i4 + Dice[3];
  248.   }
  249. }
  250.  
  251. void Find1(BYTE Board[26], BYTE Dice[4])
  252. {
  253.   int    i1,i2;
  254.   BYTE    Board1[26], Dice2[4];
  255.  
  256.   for (i2 = 0;i2 <= 1; i2++) {
  257.     Dice2[0] = Dice[i2];
  258.     Dice2[1] = 0;
  259.     Dice2[2] = 0;
  260.     Dice2[3] = 0;
  261.     for (i1 = 0;i1 <= 24; i1++)
  262.       if (Board[i1] > 0)
  263.     if (valid(Board, i1, i1 + Dice[i2], Dice[i2])) {
  264.       count++;
  265.       CopyBoard(Board,Board1);
  266.       update(Board1,i1,i1+Dice[i2],1);
  267.       FindMove(Board1,Dice2,i1,-1,-1,-1);
  268.     }
  269.   }
  270. } /* end of find1 */
  271.  
  272. void Find2(BYTE Board[26], BYTE Dice[4])
  273. {
  274.   int    i1, i2;
  275.   BYTE    Board1[26], Board2[26];
  276.  
  277.   for (i1 = 0;i1 <= 24; i1++) {
  278.     if (Board[i1] > 0)
  279.       if (valid(Board,i1,i1+Dice[0],Dice[0])) {
  280.     CopyBoard(Board,Board1);
  281.     update(Board1,i1,i1+Dice[0],1);
  282.     for (i2 = 0;i2 <= 24; i2++) {
  283.       if (Board1[i2] > 0)
  284.         if (valid(Board1,i2,i2+Dice[1],Dice[1])) {
  285.           count++;
  286.           CopyBoard(Board1,Board2);
  287.           update(Board2,i2,i2+Dice[1],1);
  288.           FindMove(Board2,Dice,i1,i2,-1,-1);
  289.         }    /* end valid Dice[1]    */
  290.     }    /* end for i2        */
  291.       }        /* end if Valid Dice[0]    */
  292.   }        /* end for i1        */
  293. }/* end find2 */
  294.  
  295. void Find3(BYTE Board[26], BYTE Dice[4])
  296. {
  297.   int    i1,i2,i3;
  298.   BYTE    Board1[26], Board2[26], Board3[26];
  299.  
  300.   for (i1 = 0;i1 <= 24; i1++) {
  301.     if (Board[i1] > 0)
  302.       if (valid(Board,i1,i1+Dice[0],Dice[0])) {
  303.     CopyBoard(Board,Board1);
  304.     update(Board1,i1,i1+Dice[0],1);
  305.     for (i2 = 0;i2 <= 24; i2++) {
  306.       if (Board1[i2] > 0)
  307.         if (valid(Board1,i2,i2+Dice[1],Dice[1])) {
  308.           CopyBoard(Board1,Board2);
  309.           update(Board2,i2,i2+Dice[1],1);
  310.           for (i3 = 0;i3 <= 24; i3++) {
  311.         if (Board2[i3] > 0)
  312.           if (valid(Board2,i3,i3+Dice[2],Dice[2])) {
  313.             count++;
  314.             CopyBoard(Board2,Board3);
  315.             update(Board3,i3,i3+Dice[2],1);
  316.             FindMove(Board3,Dice,i1,i2,i3,-1);
  317.           }    /* end valid Dice[2]    */
  318.           }        /* end for i3        */
  319.         }        /* end valid Dice[1]    */
  320.     }        /* end for i2        */
  321.       }            /* end if Valid Dice[0]    */
  322.   }            /* end for i1        */
  323. } /* end of Find3 */
  324.  
  325. void Find4(BYTE Board[26], BYTE Dice[4])
  326. {
  327.   int    i1, i2, i3, i4;
  328.   BYTE    Board1[26], Board2[26], Board3[26], Board4[26];
  329.  
  330.   for (i1 = 0;i1 <= 24; i1++) {
  331.     if (Board[i1] > 0)
  332.       if (valid(Board,i1,i1+Dice[0],Dice[0])) {
  333.     CopyBoard(Board,Board1);
  334.     update(Board1,i1,i1+Dice[0],1);
  335.     for (i2 = 0;i2 <= 24; i2++) {
  336.       if (Board1[i2] > 0)
  337.         if (valid(Board1,i2,i2+Dice[1],Dice[1])) {
  338.           CopyBoard(Board1,Board2);
  339.           update(Board2,i2,i2+Dice[1],1);
  340.           for (i3 = 0;i3 <= 24; i3++) {
  341.         if (Board2[i3] > 0)
  342.           if (valid(Board2,i3,i3+Dice[2],Dice[2])) {
  343.             CopyBoard(Board2,Board3);
  344.             update(Board3,i3,i3+Dice[2],1);
  345.  
  346.             for (i4 = 0;i4 <= 24; i4++) {
  347.               if (Board3[i4] > 0)
  348.                 if (valid(Board3,i4,i4+Dice[3],Dice[3])) {
  349.               count++;
  350.               CopyBoard(Board3,Board4);
  351.               update(Board4,i4,i4+Dice[3],1);
  352.               FindMove(Board4,Dice,i1,i2,i3,i4);
  353.             }
  354.             }    /* end for i4        */
  355.           }    /* end valid Dice[2]    */
  356.           }        /* end for i3        */
  357.         }        /* end valid Dice[1]    */
  358.         }        /* end for i2        */
  359.       }            /* end if Valid Dice[0]    */
  360.   }            /* end for i1        */
  361. } /* end of Find4 */
  362.  
  363. void GenerateMoves(BYTE Board[26], BYTE Dice[4])
  364. {
  365.   BYTE Dice2[4];
  366.  
  367.   count = 0;
  368.   PutMoveNumber(count);
  369.   /* check for doubles rolled */
  370.   if (Dice[2] != 0) {
  371.     Find4(Board,Dice);
  372.     if (count != 0)
  373.       return;
  374.     me.incomplete++;
  375.     Find3(Board,Dice);
  376.     if (count != 0)
  377.       return;
  378.     Find2(Board,Dice);
  379.     if (count != 0)
  380.       return;
  381.   }
  382.   else {
  383.     Find2(Board,Dice);
  384.     Dice2[0] = Dice[1];
  385.     Dice2[1] = Dice[0];
  386.     Dice2[2] = Dice[2];
  387.     Dice2[3] = Dice[3];
  388.     Find2(Board,Dice2);
  389.     if (count != 0)
  390.       return;
  391.     me.incomplete++;
  392.   }
  393.   Find1(Board,Dice);
  394. } /* end of generate */
  395.